
#ifndef FF_WRAPPER_GL_H
#define FF_WRAPPER_GL_H

#include <IUnityGraphics.h>
#include <IUnityGraphicsVulkan.h>

#include <platform/dynamic_library.h>

// only dynamic load is supported in plugins now
// #define FFVK_DECLARE_PROTOTYPES
#include <frame_flow_gl.h>

namespace FFSdkUnity::OpenGL {

class FFWrapperGL final {
public:
    FFWrapperGL() = default;

    FFWrapperGL(FFWrapperGL const &) = delete;
    FFWrapperGL &operator= (FFWrapperGL const &) = delete;

    FFWrapperGL(FFWrapperGL &&) = delete;
    FFWrapperGL &operator= (FFWrapperGL &&) = delete;

    ~FFWrapperGL() = default;

    [[nodiscard]] bool Init() noexcept;
    [[nodiscard]] bool Destroy() noexcept;

    [[nodiscard]] FFResult OnActivate() const noexcept;
    [[nodiscard]] FFResult OnDeactivate() const noexcept;
    [[nodiscard]] FFBool OnIsActive() const noexcept;
    [[nodiscard]] FFResult OnSetPredictionAlgorithm(FFPredictionAlgorithm algorithm, bool extrapolation) const noexcept;
    [[nodiscard]] FFResult OnSetResolution(uint32_t width, uint32_t height) const noexcept;
    [[nodiscard]] FFResult OnSetResolution2(FFResolutionInfo2 const *pResolutionInfo) const noexcept;
    [[nodiscard]] FFResult OnSetCvvZSemantic(FFCvvZSemantic semantic) const noexcept;
    [[nodiscard]] FFResult OnSetStencilRemapInfo(FFStencilValueSemantic const *pRemapTable) noexcept;
    [[nodiscard]] FFResult OnProvidePerFrameData(FFPerFrameData const *pPerFrameData) noexcept;
    [[nodiscard]] FFResult OnDrawFrame(int32_t target) noexcept;

private:
    [[nodiscard]] bool FindSDKFunctionsLib() noexcept;
    [[nodiscard]] bool FindSDKFunctionsGles() noexcept;
    void ResetSDKFunctions() noexcept;

    [[nodiscard]] bool IsInit() const noexcept;

    [[nodiscard]] bool LoadFrameFlow() noexcept;

    static void FFAPI_PTR SDKErrorCallback(char const *message, void *userData);

    // Define a list of API function pointers
#define FF_FUNCTION(func) PFN_##func func = nullptr;
#include <ff_function/ff_gl_functions.in>
#undef FF_FUNCTION

    FFInstance ffInstance_ = FF_NULL_HANDLE;
    FF::Platform::DynamicLibrary frameflowLib_{};
    // True when FF instance is provided by system via private API and must not be destroyed manually
    bool ffInstanceIsExternal_ = false;
};

} // namespace FFSdkUnity::Vulkan

#endif // FF_WRAPPER_GL_H
